#!/usr/bin/perl

use strict;
use warnings;

use POSIX qw(strftime);
use Data::Dumper;
use Time::Local;
use Time::HiRes qw(gettimeofday);

my $basedir = '/logcheck/etc';
my $datadir  = "$basedir/migrate";
my $date = strftime "%Y-%m-%d", localtime;
my $denyfile = "$datadir/syslog_deny_stat_$date";
my $level1file = "$datadir/syslog_level1_stat_$date";
my $level2file = "$datadir/syslog_level2_stat_$date";
my $badlyfile = "$datadir/badly_formatted_logs";
system("touch $denyfile");
system("touch $level1file");
system("touch $level2file");
my ($start_sec, $start_usec) = gettimeofday;
my $servername = `hostname -s`; chomp $servername;
my %hashdeny;
my $hashlevel_2; my %hashlevel_2;
my %priority=("debug"=>"7", "info"=>"6", "notice"=>"5", "warning"=>"4", "err"=>"3", "crit"=>"2", "alert"=>"1", "emerg"=>"0");
my %rpriority=reverse %priority;
my $configdir="/logcheck/etc/config";
#require("$configdir/db_mysql.pl");
require("$configdir/conndb");
my $dbh=&connect();
$dbh->do(qq{set names 'gbk'});

# set report address
# change this!
my $mailDM='fetionyy.com.cn';
my $SYSADMIN='changfugang@'.$mailDM.' '.'liweixin@'.$mailDM.' '.'hanjianye@'.$mailDM.' '.'yuyongxin@'.$mailDM.' '.'tangguorui@'.$mailDM.' '.'daixianglong@'.$mailDM;
#my $SYSADMIN='xtjc-critical@'.$mailDM.' '.'xtjc-alarm@'.$mailDM;
#my $SYSADMIN='changfugang@'.$mailDM;

my $MailFlag = 0;
my $MailSubject = "${servername}_${date}_[analysis of syslog]";
my $MailContent_other = '';
my $MailContent="BEGIN REPORT\n";
$MailContent.="------------------------------\n";
$MailContent.="Syslog Report on $servername\n";
$MailContent.="=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n";

# badly_formatted_logs
my $badlycontent = &badly_analyze($badlyfile);
chomp $badlycontent;
$MailContent .= "\n".$badlycontent."\n" if length($badlycontent) > 0;

### for FireWall
# level2 keyword result
&level2_analyze($level2file);
my ($level2content,$level2log_total) = &FireWall_echo();
chomp $level2content;
$MailContent .= "\n".$level2content."\n" if length($level2content) > 0;
# deny IP result
&deny_analyze($denyfile);
my $denycontent = &optdeny();
chomp $denycontent;
if ( length($denycontent) > 0 ){
    $MailContent .= "\nIP Deny list [top 20]:\n";
    $MailContent .= $denycontent."\n";
}

# level1 keyword result
my ($level1content,$level1log_total) = &level1_analyze($level1file);
$MailContent .= "\nUndefine keywords:\n";
chomp $level1content;
if ( length($level1content) > 0 ){
	$MailContent .= $level1content."\n";
        $MailFlag=1;
}else{
        $MailContent .= "NULL\n";
}

my $log_total = $level2log_total + $level1log_total;
$MailContent .= "\n".$log_total." lines syslog record were analyzed.\n";

my ($end_sec, $end_usec) = gettimeofday;
my $time_used = ($end_sec - $start_sec) + ($end_usec - $start_usec)/1000000;
$time_used = &conv_date_tostr($time_used);
$MailContent .= "$time_used\n";

$MailContent .= "END OF REPORT\n";
print $MailContent."\n";


&sendmail($SYSADMIN,$MailFlag,$MailSubject,$MailContent);


### analyse the migrate
### __START__
#
sub badly_analyze
{
    my $logfile = shift;
    my $badlycontent='';
    open(BADLYFID, "<$logfile") or die "can't open file $logfile";
    while(<BADLYFID>){
        chomp;
        $badlycontent.=$_."\n";
    }
    close BADLYFID;
    return $badlycontent;
}

sub deny_analyze
{
    my $logfile = shift;
    open(DENYFID, "<$logfile") or die "can't open file $logfile";
    while(<DENYFID>){
        chomp;
        my ($host,$IP,$key,$count) = split(/\,/,$_);
        if( exists( $hashdeny{"${host}_${IP}_$key"} ) )
        {
                $hashdeny{"${host}_${IP}_$key"} += $count;
        }
        else
        {
                $hashdeny{"${host}_${IP}_$key"} = $count;
        }
    }
    close DENYFID;
}

sub level1_analyze
{
    my $logfile = shift;
    my $level1content='';
    my $count=0;
    open(LSTFID, "<$logfile") or die "can't open file $logfile";
    while(<LSTFID>){
        chomp;
	$count+=1;
        $level1content.=$_."\n";
    }
    close LSTFID;
    return ($level1content,$count);
}

sub level2_analyze
{
    my $logfile = shift;
    open(LNDFID, "<$logfile") or die "can't open file $logfile";
    while(<LNDFID>){
        chomp;
        my ($host,$IP,$level,$key,$count) = split(/\,/,$_);
        if( exists( $hashlevel_2->{"${host}_$IP"}{$level}{$key} ) )
        {
                $hashlevel_2->{"${host}_$IP"}{$level}{$key} += $count;
        }
        else
        {
                $hashlevel_2->{"${host}_$IP"}{$level}{$key} = $count;
        }

    }
    close LNDFID;
}
#
### analyse the migrate
### _END_


### print it to screen or sendmail
### __START__
#
sub FireWall_echo
{
    my $MailContent = '';
    # level2
    my $hash_lvl_tcnt;my %hash_lvl_tcnt;
    foreach my $key1 (keys %$hashlevel_2)
    {
        foreach my $key2 (keys %{$hashlevel_2->{$key1}})
        {
            foreach my $key3 (keys %{$hashlevel_2->{$key1}{$key2}})
            {
                $hash_lvl_tcnt->{$key1}{$key2} += $hashlevel_2->{$key1}{$key2}{$key3};
            }
        }
    }
    
    my %hash_host_tlvl;
    foreach my $key1 (keys %$hash_lvl_tcnt)
    {
        foreach my $key2 (keys %{$hash_lvl_tcnt->{$key1}})
        {
            #print $hash_lvl_tcnt->{$key1}{$key2}."\n";
            $hash_host_tlvl{$key1} += $hash_lvl_tcnt->{$key1}{$key2};
        }
    }
    
    my $log_total=0;
    foreach my $key (keys %hash_host_tlvl)
    {
        $log_total += $hash_host_tlvl{$key};
    }
    
    while ( my($key1, $value1) = each(%$hashlevel_2) )
    {
        my $host = $key1;
        $MailContent .= "\n".$host." (:$hash_host_tlvl{$host})\n";
    
        while ( my($key2, $value2) = each(%$value1))
        {
            my $level = $key2;
            my $turnlevel = $priority{$level};
            my $hblankline = " " x length($host);
            $MailContent .= $hblankline."|\n";
            $MailContent .= $hblankline."|_ ".$turnlevel."[$level]"." (:$hash_lvl_tcnt->{$host}{$level})\n";
    
            foreach my $key3 (sort keys %$value2)
            {
                my $content_name = $key3;
                my $lblankline = " " x (length($level)+2);
                my $content_value = $hashlevel_2->{$key1}{$key2}{$content_name};
                $MailContent .= $hblankline.$lblankline."|_ ".$content_name." \t=>\t".$content_value."\n";
                &optlevel2($host,$level,$content_name,$content_value);
            }
        }
    
    }

    $MailContent .= "\n";

    return ($MailContent,$log_total);
}

#
### print it to screen or sendmail
### __END__


### define output style
### __START__
#
# no optlevel1

sub optdeny{
    my $denycontent='';
    my $flag=1;
    my @sorted = map { { ($_ => $hashdeny{$_}) } } sort {$hashdeny{$b}<=>$hashdeny{$a}} keys %hashdeny;
    foreach my $hashref (@sorted) {
      $flag+=1;
      if ($flag<=21) {
            my ($key, $value) = each %$hashref;
            #print "$key => $value\n";
            my ($host,$IP,$keyword) = split(/\_/,$key);
            if ($key =~ m/deny|denied/i){
                $denycontent.="${host}_${keyword}_$IP => $value\n";
                &database_denyip($host,$IP,$keyword,$value);
	    }
      }else{
            last;
      }
    }
    return $denycontent;
}

sub optlevel2 {
    my ($hostname,$level,$content_name,$content_account) = @_;
    my $host = (split(/\_/,$hostname))[0];
    my $ip = (split(/\_/,$hostname))[1] ||$host;
    &database_level2($host,$ip,$level,$content_name,$content_account);
}
#
### define output style
### __END__


### write database
### __START__
#
sub database_level2 {
        my ($host,$ip,$level,$content_name,$content_account) = @_;
        chomp $content_account;
        my $table_name = "logstats_level2";
        my $columns = '`host`,`ip`,`level`,`tag`,`counter`,`fo`';
        my $values = "\"$host\",\"$ip\",\"$level\",\"$content_name\",\"$content_account\",\"$date\"";
        # Write to mysql database
        ## write level2 data
        my $sth=$dbh->do(qq{INSERT INTO $table_name ( $columns ) value ( $values )});
        my $string = "INSERT INTO $table_name ( $columns ) value ( $values )";
        return $string;
}

sub database_denyip {
        my ($host,$ip,$tag,$counter) = @_;
        chomp $counter;
        my $table_name = "ip_deny_info";
        my $columns = '`host`,`ip`,`tag`,`counter`,`fo`';
        my $values = "\"$host\",\"$ip\",\"$tag\",\"$counter\",\"$date\"";
        # Write to mysql database
        ## write denyip data
        my $sth=$dbh->do(qq{INSERT INTO $table_name ( $columns ) value ( $values )});
        my $string = "INSERT INTO $table_name ( $columns ) value ( $values )";
        return $string;
}
# no database_level1
#
### write database
### __END__

sub sendmail{
        my $MailFrom = 'report@syslog.feinno.com';
        my ($MailTo,$MailFlag,$MailSubject,$MailContent) = @_;
        if ($MailFlag == 1) {
                $MailFlag = "X-Priority: 1 (Highest)\n";
                $MailFlag .= "X-MSMail-Priority: High\n";
                $MailFlag .= "Importance: High\n";
        }else{
                $MailFlag = "";
        }
        open(FD,"|/usr/sbin/sendmail -fadmin -t>/dev/null") || die "sendmail fail! $!\n";
        print FD "To:$MailTo\n";
        print FD "From:$MailFrom\n";
        print FD "Subject:$MailSubject\n";
        print FD "$MailFlag\n";
        print FD "$MailContent";
        close(FD);
}

sub conv_date_tostr {
    my $ts = shift;
    #my ($sec,$min,$hour,$mday,$mon,$year) = localtime($ts);
    #my $timestamp = timelocal($sec,$min,$hour,$mday,$mon,$year);
    #sprintf "time used: %.3fs",$timestamp;
    sprintf("time used: %.3fs", $ts);
}
